/*
 * =====================================================================================
 *
 *       Filename:  mainWindow.h
 *
 *        Version:  2.3
 *        Created:  09/11/13 12:50:50
 *
 *         Author:  LIU RENSHENG (A0105649B), roastedbill@gmail.com
 *   Organization:  NUS, SoC
 *
 * =====================================================================================
 */

/**************************************************************************
 *        This Library describe the main window for our GUI               *
 *    It takes input from user and give feedback in the bottom window     *
 * It can also generate multiple child windows which are able to be moved *
 **************************************************************************/

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtWidgets/QMainWindow>
#include <QtCore/QTextStream>
#include <QKeyEvent>
#include <QShortcut>
#include <QStack>
#include <QTextLayout>
#include <QSystemTrayIcon>
#include <QTimer>
#include "ui_mainWindow.h"
#include "Logic.h"
#include "feedbackWindow.h"

/*==================*
 *For mainWindow.cpp*
 *==================*/

//@author A0105649B
// Defining Key Words
const QString CREATE_KEYWORD1          = "create";
const QString CREATE_KEYWORD2          = "add";
const QString DISPLAY_KEYWORD1         = "display";
const QString DISPLAY_KEYWORD2         = "read";
const QString DELETE_KEYWORD1          = "delete";
const QString DELETE_KEYWORD2          = "remove";
const QString UPDATE_KEYWORD1          = "update";
const QString UPDATE_KEYWORD2          = "renew";
const QString SEARCH_KEYWORD1          = "search";
const QString SEARCH_KEYWORD2          = "find";
const QString UNDO_KEYWORD             = "undo";
const QString REDO_KEYWORD             = "redo";
const QString MARK_KEYWORD             = "mark";
const QString UNMARK_KEYWORD           = "unmark";
const QString EXIT_KEYWORD1            = "exit";
const QString EXIT_KEYWORD2            = "quit";


// Output Keywords
const QString DISPLAY_CREATE_KEYWORD   = "create";
const QString DISPLAY_DISPLAY_KEYWORD  = "display";
const QString DISPLAY_DELETE_KEYWORD   = "delete";
const QString DISPLAY_UPDATE_KEYWORD   = "update";
const QString DISPLAY_SEARCH_KEYWORD   = "search";
const QString DISPLAY_UNDO_KEYWORD     = "undo";
const QString DISPLAY_REDO_KEYWORD     = "redo";
const QString DISPLAY_EXIT_KEYWORD     = "exit";
const QString DISPLAY_MARK_KEYWORD     = "mark";
const QString DISPLAY_UNMARK_KEYWORD   = "unmark";

// Feedback QString
const QString DISPLAY_CREATE_FEEDBACK  = "eg. create /t meeting /l nus /pe Bill /de bring notes! /st 0900 /d 12 Nov 2013 /et 2200 /d 12/11/2013 /pr high\n\nTitle: /t + <title>\n\nLocation: /l + <location>\n\nPerson: /pe + <person>\n\nDescription: /de + <Info>\n\nStart time: /st + <start time> --- eg: 2100, 0900\n\nEnd time: /et + <end time> --- eg: 2100, 0900\n\nDate: /d + <Date> --- dd/mm/yyyy (this means the date of the last time you have input)\n\nPriority: /pr + <0 to 2> or High, Medium, Low\n";
const QString DISPLAY_DISPLAY_FEEDBACK = "display: display all tasks\n\ndisplay + <index>: display certain task\neg. display 1\n\ndisplay + <attributeType>: display tasks sorted by attribute\neg. display /f, display /st";
const QString DISPLAY_SEARCH_FEEDBACK  = "eg. search /t test /l MPSH\n\nTitle: /t + <title>\n\nLocation: /l + <location>\n\nPerson: /pe + <person>\n\nDescription: /de + <Info>\n\nStart time: /st + <start time> --- eg: 0900, 1200\n\nEnd time: /et + <end time> --- eg:0900, 1200\n\nDate: /d + <Date> --- dd/mm/yyyy (this means the date of the last time you have input)\n\nPriority: /pr + <0 to 2> or High, Medium, Low\n\nFinished: /f + <0 or 1> or not finished, finished\n";
const QString DISPLAY_DELETE_FEEDBACK  = "delete + <index>\n eg. delete 10\n(check the index by using search function)";
const QString DISPLAY_UPDATE_FEEDBACK  = "eg. update 20 /pr high\n\nindex must be input first (check the index by using search function)\n\nTitle: /t + <title>\n\nLocation: /l + <location>\n\nPerson: /pe + <person>\n\nDescription: /de + <Info>\n\nStart time: /st + <start time> --- eg: 0900, 1200\n\nEnd time: /et + <end time> --- eg: 0900, 1200\n\nStart Date: /sd + <Date> --- dd/mm/yyyy\n\nEnd Date: /ed + <Date> --- dd/mm/yyyy\n\nPriority: /pr + <0 to 2> or High, Medium, Low\n\nFinished: /f + <0 or 1> or not finished, finished\n";
const QString DISPLAY_UNDO_FEEDBACK    = "Undo last operation\n";
const QString DISPLAY_REDO_FEEDBACK    = "Redo last undo operation\n";
const QString DISPLAY_MARK_FEEDBACK    = "eg. mark 25\nMark task 25 as finished \n";
const QString DISPLAY_UNMARK_FEEDBACK  = "eg. unmark 12\nMark task 12 as not finished\n";
const QString DISPLAY_EXIT_FEEDBACK    = "Do you want to quit TaskLine?\n";

// Define quit Feedback and file name
const QString EXIT_FEEDBACK            = "See You Again";
const QString FILE_NAME                = "taskfile.txt";

// Define style sheets
const QString CENTRAL_WIDGET_STYLE     = "QWidget#centralWidget {background:transparent;}";
const QString INPUT_LINE_STYLE         = "background:transparent;"; 

// Define icon name
const QString ICON_NAME_STRING         = "taskLineIcon.ico";

// Defining for mark/unmark QString conversion
const QString TRANSLATE_MARK           = " /f 1";
const QString TRANSLATE_UNMARK         = " /f 0";
const QString SPACE                    = " ";

// Defining for tray icon
const QString TOOL_TIP                 = "TaskLine!";
const QString TRAY_ICON_PATH           = ":/TaskLine/taskLineIcon.png";

// Define default display 
const string  DEFAULT_DISPLAY_STRING   = "/default"; 

// Define position elements for main window and child windows
const int     INITIAL_MAIN_POSX        = 0;
const int     INITIAL_MAIN_POSY        = 0;
const int     INITIAL_CHILD_POSX       = 100;
const int     INITIAL_CHILD_POSY       = 40;
const int     CHILD_POS_DIFFERENCEX    = 2;
const int     CHILD_POS_DIFFERENCEY    = 4;
const int     MAX_CHILD_POSY           = 60;

// Defining keyword lengths
const int     MAX_KEY_LENGTH           = 7;
const int     KEYWORD_LENGTH4          = 4;
const int     KEYWORD_LENGTH6          = 6;
const int     KEYWORD_LENGTH7          = 7;
const int     BASE                     = 0;
const int     SINGLE                   = 1;

// Defining for mark/unmark QString conversion
const int     INDEX_PART               = 1;

// For QTimer
const int     RIGHT_AWAY               = 0;

class mainWindow : public QMainWindow
{
	Q_OBJECT

public:
	mainWindow                         (QWidget *parent = 0);
	~mainWindow                        ();

	private slots:
		// triggered when return is pressed in text bar
		void processing                ();

		// triggered when keywords are input by user
		void changeTextAttribute       ();

		// Handle key combinations
		void handleQuit                ();
		void handleKeyCtrlD            (); // Delete the whole line
		void handleKeyCtrlM            (); // Minimize the window
		void handleKeyCtrlTab          (); // Works when there's only a keyword in the input line
		void iconIsActived             (QSystemTrayIcon::ActivationReason); // Minimize program to Tray Icon
	
private:
	// Components
	Ui::mainWindow                     ui;
	Logic                              logic;

	// Flag for deleting keywords
    bool                               isOnlyKeyword;

	// Mouse position
	QPoint                             windowPos;
	QPoint                             mousePos;
	QPoint                             dPos;

	// Child windows position difference
	QPoint                             relativePos;
	QPoint                             posDifference;

	// Recording input commands
	QStack<QString>                    inputRecordIn;
	QStack<QString>                    inputRecordOut;

	// Font formats for keywords
	QList<QTextLayout::FormatRange>    formats;
	QTextCharFormat                    createFormat;
	QTextCharFormat                    displayFormat;
	QTextCharFormat                    deleteFormat;
	QTextCharFormat                    updateFormat;
	QTextCharFormat                    searchFormat;
	QTextCharFormat                    undoFormat;
	QTextCharFormat                    redoFormat;
	QTextCharFormat                    markFormat;
	QTextCharFormat                    unmarkFormat;
	QTextCharFormat                    exitFormat;

	// For minimizition to tray icon
	QSystemTrayIcon *                  trayIcon;

	// Set up memory
	void    setupFileStream            (string);

	// Initializing GUI functions
	void    changeUIStyle              ();
	void    setupTrayIcon              ();
	void    setMainWidgetStyle         ();
	void    setComponentsStyle         ();
	void    connectSingleKeyEvents     ();  
	void    connectMultiKeyEvents      ();
	void    displayDefaultContent      ();	// In order of start time 
	void    initializeParameters       ();
 
	// Setting keyword to Input Line
	void    setKeywordCreate           ();
	void    setKeywordDisplay          ();
	void    setKeywordDelete           ();
	void    setKeywordUpdate           ();
	void    setKeywordSearch           ();
	void    setKeywordUndo             ();
	void    setKeywordRedo             ();
	void    setKeywordMark             ();
	void    setKeywordUnmark           ();
	void    setKeywordExit             ();

	// Setting keyword formats
	void    setKeywordFormatCreate     ();
	void    setKeywordFormatDisplay    ();
	void    setKeywordFormatDelete     ();
	void    setKeywordFormatUpdate     ();
	void    setKeywordFormatSearch     ();
	void    setKeywordFormatUndo       ();
	void    setKeywordFormatRedo       ();
	void    setKeywordFormatMark       ();
	void    setKeywordFormatUnmark     ();
	void    setKeywordFormatExit       ();
 
	// Linking with main functions
	QString getCommandLine             ();
	string  executeCommand             (QString);
	void    triggerFeedback            (string);
	void    resetMainWindow            ();
	void    generateFeedbackNote       (QString);
	QString handleMarkUnmark           (QString);
 
	// Handle keyboard input
	void    keyPressEvent              (QKeyEvent*);
	void    handleKeyUp                ();
	void    handleKeyDown              ();
 
	// Operation Records --- for keyboard input UP and DOWN
	void    saveToRecord               (QString);
	void    resetRecord                ();         // push the record in outStack back to inStack
	void    pushToRecordStack          (QString);
	void    deleteRepeatedRecord       (QString);  // checking the stack size and try to delete
	void    deleteRecordFromStack      (QString);  // check and delete the repeated record
	void    showLastRecord             (QStack<QString>*,QStack<QString>*);
	void    showLastRecordWithoutPop   (QStack<QString>*,QStack<QString>*);

	// Changing font and color of keywords
	void    constructFormat            (QTextCharFormat&);
	void    setUpFormateModifier       ();
	void    setLineEditTextFormat      (QLineEdit*, const QList<QTextLayout::FormatRange>&);
	void    clearLineEditTextFormat    (QLineEdit*);
	void    constructLayoutFormat      (int, QTextCharFormat);

	// Suggestion feedback for inputing factors
	void    bumpOutSuggestionCreate    ();
	void    bumpOutSuggestionDisplay   ();
	void    bumpOutSuggestionDelete    ();
	void    bumpOutSuggestionUpdate    ();
	void    bumpOutSuggestionSearch    ();
	void    bumpOutSuggestionUndo      ();
	void    bumpOutSuggestionRedo      ();
	void    bumpOutSuggestionMark      ();
	void    bumpOutSuggestionUnmark    ();
	void    bumpOutSuggestionExit      ();
 
	// Changing format between QString and string
	QString s2q                        (const string &s);  
	string  q2s                        (const QString &s);

	// Dragging mainWindow
	void    mousePressEvent            (QMouseEvent *);
	void    mouseMoveEvent             (QMouseEvent *);

	// Initialize child window position
	void    initializeRelativePos      ();
	void    modifyRelativePos          ();

	// Detecting Keywords
	void    setIsOnlyKeyword           ();
	void    clearIsOnlyKeyword         ();

	// File related operations
	void    saveToFile                 ();
	void    loadFromFile               (string);
};


#endif
